package com.chris.cc.user.service.impl;

import com.chris.cc.common.exception.InvalidArgumentException;
import com.chris.cc.user.mapper.PermissionMapper;
import com.chris.cc.user.mapper.RolePermissionMapper;
import com.chris.cc.user.model.dto.PermissionDto;
import com.chris.cc.user.model.entity.Permission;
import com.chris.cc.user.model.entity.Role;
import com.chris.cc.user.model.entity.RolePermission;
import com.chris.cc.user.service.PermissionService;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 * Copyright (c) 2018-2025, chris All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * <p>
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * <p>
 * Author: haoka (haokang207@126.com)
 * <p>
 * Date: 2018/8/24 11:03
 **/
@Service
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Override
    public Permission add(PermissionDto permission) throws InvalidArgumentException {
        Permission u = Permission.builder()
                .code(permission.getCode())
                .name(permission.getName())
                .description(permission.getDescription())
                .parentId(permission.getParentId())
                .build();
        u.setModifyDate(new Date());
        u.setCreateDate(new Date());
        try {
            permissionMapper.insert(u);
        } catch (DuplicateKeyException e) {
            throw new InvalidArgumentException("代码已存在", permission.getCode());
        }
        return u;
    }

    @Override
    public Page<Permission> query(Long parentId, Boolean enable, String keyword, Pageable page) {
        Example e = new Example(Permission.class);
        Example.Criteria criteria = e.createCriteria();
        if (parentId != null) {
            criteria.andEqualTo("parentId", parentId);
        }
        if (enable != null) {
            criteria.andEqualTo("enable", enable);
        }
        if (StringUtils.isNotBlank(keyword)) {
            Example.Criteria or = e.createCriteria();
            or.orLike("name", "%" + keyword + "%");
            or.orLike("code", "%" + keyword + "%");
            or.orLike("description", "%" + keyword + "%");
            e.and(or);
        }
        RowBounds rowBounds = new RowBounds(Long.valueOf(page.getOffset()).intValue(), page.getPageSize());
        List<Permission> list = permissionMapper.selectByExampleAndRowBounds(e, rowBounds);
        int total = permissionMapper.selectCountByExample(e);
        return new PageImpl<>(list, page, total);
    }

    @Override
    public void delete(Long permissionId) {
        Example e = new Example(RolePermission.class);
        e.createCriteria().andEqualTo("permissionId", permissionId);
        rolePermissionMapper.deleteByExample(e);
        permissionMapper.deleteByPrimaryKey(permissionId);
    }

    @Override
    public Permission update(PermissionDto permission) throws InvalidArgumentException {
        if (permission.getPermissionId() == null) {
            return null;
        }
        Permission u = Permission.builder()
                .permissionId(permission.getPermissionId())
                .parentId(permission.getParentId())
                .name(permission.getName())
                .code(permission.getCode())
                .description(permission.getDescription())
                .build();
        u.setModifyDate(new Date());
        try {
            permissionMapper.updateByPrimaryKeySelective(u);
        } catch (DuplicateKeyException e) {
            throw new InvalidArgumentException("名称或代码已存在", e.getMessage());
        }
        return permissionMapper.selectByPrimaryKey(permission.getPermissionId());
    }

    @Override
    public List<Permission> getByCode(String... code) {
        if (code == null || code.length == 0) {
            return Collections.emptyList();
        }
        Set<String> codes = new HashSet<>();
        for (String c : code) {
            if (StringUtils.isNotBlank(c)) {
                codes.add(c.trim());
            }
        }
        if (codes.isEmpty()) {
            return Collections.emptyList();
        }
        Example e = new Example(Role.class);
        e.createCriteria().andIn("code", codes);
        return permissionMapper.selectByExample(e);
    }

    @Override
    public List<Permission> getByUserId(Long userId) {
        if (userId == null) {
            return Collections.emptyList();
        }
        return rolePermissionMapper.selectPermissionByUserId(userId);
    }

    @Override
    public List<Permission> updateRolePermission(Long roleId, Long[] permissionIds) {
        if (roleId == null) {
            return Collections.emptyList();
        }
        Example e = new Example(RolePermission.class);
        e.createCriteria().andEqualTo("roleId", roleId);
        rolePermissionMapper.deleteByExample(e);
        List<Permission> list = new ArrayList<>();
        for (Long permissionId : permissionIds) {
            if (permissionId != null) {
                Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
                if (permission == null) {
                    continue;
                }
                list.add(permission);
                RolePermission p = RolePermission.builder()
                        .roleId(roleId)
                        .permissionId(permissionId)
                        .build();
                p.setCreateDate(new Date());
                rolePermissionMapper.insert(p);
            }
        }
        return list;
    }

    /**
     * 获取角色的权限列表
     *
     * @param roleId
     * @return
     */
    @Override
    public List<Permission> getByRoleId(Long roleId) {
        if (roleId == null) {
            return Collections.emptyList();
        }
        return rolePermissionMapper.selectPermissionByRoleId(roleId);
    }

    @Override
    public Permission getById(Long id) {
        return permissionMapper.selectByPrimaryKey(id);
    }
}
